# -*- coding: utf8 -*-


class Semantico:
    
    objeto = ''
    constantes = ''  # onde ficam os Ks
    contador_constantes = 0
    pilha_operandos = []
    pilha_operadores = []
    
    tabelaSimbolos = None
    
    contatorTemp = 0
    contadorIF = 0
    tipoOperacao = ''
    
    expressao1 = ''
    comparador = ''
    expressao2 = ''
    
    identificador = ''
    
    def __init__(self, tabelaSimbolos):
        self.tabelaSimbolos = tabelaSimbolos
    
    #########################################    
    ###  operacoes com a maquina programa ###
    #########################################  
    
    def IniciarCodigoObjeto(self):
        self.objeto = '@ /0000 ; inicio de programa no endereço 0x0000 \n'
        self.objeto = self.objeto + 'JP INICIO ; vai para inicio do programa \n'
        
    def TerminarCodigoObjeto(self):
        self.objeto = self.objeto + 'HM /00 ; fim de programa no endereço 0x0000 \n'
        
    def DeclaraVariavel(self, variavelNome, tipo):
        #self.tabelaSimbolos.AdicionarSimbolo(variavelNome)
        self.tabelaSimbolos.PoeRotulo(variavelNome, variavelNome)
        self.tabelaSimbolos.PoeTipo(variavelNome, tipo)
        print self.tabelaSimbolos.tabela
        self.objeto = self.objeto + ' '+  variavelNome + ' K /0000 ; variavel \n'
    
    def print_hex(self, hexa):
        hexa = hexa[2:]
        if len(hexa) == 1:
            return '000' + hexa
        elif len(hexa) == 2:
            return '00' + hexa
        elif len(hexa) == 3:
            return '0' + hexa
        elif len(hexa) == 4:
            return hexa
    
    #########################################    
    ### operações com a máquina expressão ###
    #########################################    
    
    def EmpilhaOperando(self, operando, tipoToken):
        print 'SEMANTICO - Empilhou operando:' + operando
        self.pilha_operandos.append((operando, tipoToken))
        print 'SEMANTICO - Pilha operando:', self.pilha_operandos
        
    def EmpilhaOperador(self, operador):
        print 'SEMANTICO - Empilhou operador:' + operador
        self.pilha_operadores.append(operador)
        
    def FecharParenteses(self):
        while self.pilha_operadores[len(self.pilha_operadores)] <> '(':
            self.GeraCodigoExpressao
        # desempilha '('
        self.pilha_operandos.pop()
    
    def TratarOperador(self, operador):
        if len(self.pilha_operadores) >0:
            topo = self.pilha_operadores[len(self.pilha_operadores) - 1]
        else:
            topo = ''
        print 'Passou Tratar Operador: ' + operador
        if operador == '+' or  operador == '-':
            if topo == '+' or topo == '-' or topo == '*' or topo == '/':
                self.GeraCodigoExpressao()
            else:
               self.EmpilhaOperador(operador)
        elif operador == '*' or  operador == '/':
            if topo == '*' or topo == '/':
                self.GeraCodigoExpressao()
            else:
               self.EmpilhaOperador(operador)
    
    def GeraCodigoExpressao(self):
        y = self.pilha_operadores.pop()
        b = self.pilha_operandos.pop()[0]
        a = self.pilha_operandos.pop()[0]
        tipoA = self.tabelaSimbolos.PegaTipo(a)
        tipoB = self.tabelaSimbolos.PegaTipo(b)
        rotuloA = self.tabelaSimbolos.PegaRotulo(a)
        rotuloB = self.tabelaSimbolos.PegaRotulo(b)
        
        print 'SEMANTICO - B: ' + b 
        print 'SEMANTICO - A: ' + a
        print 'SEMANTICO - tipoB: ' + str(tipoB) 
        print 'SEMANTICO - tipoA: ' + str(tipoA)
        print 'SEMANTICO - rotuloB: ' + str(rotuloB)
        print 'SEMANTICO - rotuloA: ' + str(rotuloA)
        
        # A ou B são inteiros
        if tipoB == None:
            rotuloB = '/' + self.print_hex(hex(int(b)))
        if tipoA == None:
            rotuloA = ' LV /' + self.print_hex(hex(int(a)))
        else:
            rotuloA = a
            rotuloA = ' LD ' + rotuloA
        
        self.expressao1 = self.expressao1 + rotuloA + '\n'
        
        if y == '+':
            self.expressao1 = self.expressao1 + ' + ' + rotuloB + '\n'
        elif y == '-':
            self.expressao1 = self.expressao1 + ' - ' + rotuloB + '\n'
        elif y == '/':
            self.expressao1 = self.expressao1 + ' / ' + rotuloB + '\n'
        elif y == '*':
            self.expressao1 = self.expressao1 + ' * ' + rotuloB + '\n'
        
        # incrementa contator temporário
        self.contatorTemp = self.contatorTemp + 1
        
        self.expressao1 = self.expressao1 + ' MM TEMP'+ str(self.contatorTemp) +'\n'
        
        self.EmpilhaOperando('TEMP'+ str(self.contatorTemp), 'rotulo')
        
    def CopiaExpressaoParaObjeto(self):
        print 'sem - ' + self.expressao1
        self.objeto = self.objeto + self.expressao1
        self.expressao1 = ''
    
    # retornar o código da expressao e zera a pilha de expressao
    def RetornaCodigoExpressao(self):
        self.pilha_operandos = []
        return self.expressao1
    

    
    #########################################    
    ###  operações com a máquina comando  ###
    #########################################
    
    def ArmazenarIdentificador(self, id):
        self.identificador = id
    
    def AtribuirValor(self, identificador):
        rotuloID = self.tabelaSimbolos.PegaRotulo(identificador)
        tupla = self.pilha_operandos.pop()
        item, tipo = tupla[0], tupla[1]
        print 'tipo' + tipo
        valor = ''
        if tipo == 'rotulo' or tipo == 'Identificador':
            valor =  ' LD ' + item
        else:
            print str(hex(int(item)))
            valor = ' LV /' + self.print_hex(hex(int(item)))
        
        self.objeto = self.objeto + valor + '\n MM '+ identificador + ' ; atribui valor a variavel ' + identificador +'\n'
    
    def GeraCodigoComando_Leitura(self, identificador):
        rotuloID = self.tabelaSimbolos.PegaRotulo(identificador)
        self.objeto = self.objeto + ' GD '+ rotuloID +'\n'
        
    def GeraCodigoComando_Escrita(self, expressao):
        #rotuloID = self.tabelaSimbolos.PegaRotulo(expressao)
        self.objeto = self.objeto + ' PD '+ expressao +'\n'
       
    def IfCodigoComando(self, tipoOp):
        self.contadorIF = self.contadorIF + 1
        if tipoOp == '==':
            # TODO: print "- Variavel contida no 'i'  "
            print "JZ IF_" + contadorIF
            print "JP ELSE_" + contadorIF                    
        elif tipoOp == '>':
            # TODO: print "- Variavel contida no 'i'  "
            print "JN IF_" + contadorIF
            print "JP ELSE_" + contadorIF            
        elif tipoOp == '<':
            # TODO: print "- Variavel contida no 'i'  "
            print "JN IF_" + contadorIF
            print "JP ELSE_" + contadorIF
        
        
    def GuardaTemporario(self):
        self.objeto = self.objeto + ' MM   #TEMP \n'
        
               
    def GuardaComparador(self, comparador):
        if comparador == '==':
            tipoOperacao == '=='
        elif comparador == '>':
            tipoOperacao == '>'
        elif comparador == '<':
            tipoOperacao == '<'
        elif comparador == '>=':
            tipoOperacao == '>='
        elif comparador == '<=':
            tipoOperacao == '<='
            
            
            
    def GravaNoArquivo(self):
        f = open('C:\\Users\\Celso\\Desktop\\comp\\saida.asm', 'w')
        f.write(self.objeto)
        f.close()
        
